package com.ysd.lis.aspect;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ysd.lis.annotation.MainInfoLog;
import com.ysd.lis.controller.lab.LabMaininfoController;
import com.ysd.lis.entity.SysOrganization;
import com.ysd.lis.entity.SysUser;
import com.ysd.lis.entity.lab.LabMainInfoLog;
import com.ysd.lis.entity.lab.LabMaininfo;
import com.ysd.lis.mapper.sys.SysOrganizationMapper;
import com.ysd.lis.service.lab.LabMainInfoLogService;
import com.ysd.lis.service.lab.LabMaininfoService;
import com.ysd.lis.util.compare.CompareUtils;
import com.ysd.util.RedisUserManager;
import com.ysd.util.ToolsUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiFunction;
import java.util.stream.Collectors;


/**
 * @author LuoXS
 * @date 2024/5/23
 * version 1.0
 */
@Order(1)
@Aspect
@Component
public class MainInfoLogAspect {


    @Resource
    SysOrganizationMapper sysOrganizationMapper;
    @Resource
    LabMainInfoLogService logService;
    @Autowired
    LabMaininfoService labMaininfoService;

    private static final Logger logger = LoggerFactory.getLogger(LabMaininfoController.class);


    private final static Map<String, String> mainInfoMap = new HashMap<String, String>() {
        {
            put("id", "主键");
            put("rptGroup", "报告单元");
            put("rptGroupNa", "报告单元名称");
            put("sampleda", "检验日期");
            put("sampleNo", "标本号");
            put("isUrgent", "加急急诊标志0否1是");
            put("reqNo", "条码号");
            put("reqTime", "申请时间");
            put("sampleType", "样本类型编号");
            put("quantity", "标本量");
            put("feeType", "费别");
            put("reqDept", "申请科室编号");
            put("reqWard", "病区代码");
            put("reqDoctor", "申请医生编号");
            put("reqPurpose", "检验目的，如肝功，肾功，血糖");
            put("testPurpose", "检验目的");
            put("reSampleNo", "复查标本号");
            put("patType", "病人类型");
            put("patNo", "病历号");
            put("patNa", "病人姓名");
            put("patPyName", "姓名拼音码");
            put("sex", "性别1男、2女、3不详");
            put("idType", "证件类型来自字典");
            put("idNo", "身份证号");
            put("sin", "社会保险号码");
            put("bedNo", "床号");
            put("age", "年龄");
            put("ageUnit", "年龄单位");
            put("secAge", "二级年龄");
            put("telNo", "联系电话");
            put("contacter", "联系人(病人家属)");
            put("phyCycel", "生理周期");
            put("lactation", "哺乳期");
            put("gestation", "妊娠期");
            put("gestationWeek", "孕周数");
            put("gestationTimes", "孕次数");
            put("gestationStage", "孕期");
            put("diagnose", "临床诊断");
            put("description", "备注");
            put("testDoctor", "检验医生编号/上机人");
            put("testTime", "检验时间（上机时间）");
            put("isChk", "是否审核");
            put("chkDoctor", "审核医生编号");
            put("chkTime", "审核时间");
            put("isReChk", "是否复核");
            put("firstChkDoctor", "初审医生编号");
            put("firstChkTime", "初审时间");
            put("reChkDoctor", "复核医师编号");
            put("reChkTimt", "复核日期");
            put("isPrint", "是否打印");
            put("printDoctor", "打印人编号");
            put("printTime", "打印时间");
            put("printCount", "打印次数");
            put("isPublish", "是否发布");
            put("samplingDoctor", "采样医生编号");
            put("samplingTime", "采样时间");
            put("samplingSite", "采集部位");
            put("traits", "标本特征");
            put("signerDoctor", "签收人编号");
            put("signTime", "签收时间");
            put("isDouble", "双向标志");
            put("isAlarm", "是否危急值");
            put("isAutoPrint", "是否自助打印");
            put("autoPrintTime", "自助机打印时间");
            put("isLock", "是否锁定");
            put("isCancel", "是否作废");
            put("alarmResult", "报警结果");
            put("positiveFlag", "阳性结果标志");
            put("remake1", "备注1");
            put("remake2", "备注2");
            put("remake3", "备注3");
            put("remake4", "备注4");
            put("executeFlag", "仪器调用接口执行标志");
            put("businessType", "报告单元-业务类型");
            put("sampleTypeNa", "样本类型名称");
            put("reqDeptNa", "申请科室名称");
            put("patTypeNa", "病人类型");
            put("sexNa", "性别");
            put("idTypeNa", "证件类型");
            put("reqDoctorNa", "申请医生名称");
            put("testDoctorNa", "检验医生名称");
            put("chkDoctorNa", "审核医生名称");
            put("unChkDoctor", "授权后消审医生编号");
            put("unChkDoctorNa", "授权后消审医生名称");
            put("reChkDoctorNa", "复核医师名称");
            put("printDoctorNa", "打印人名称");
            put("samplingDoctorNa", "采样医生名称");
            put("signerDoctorNa", "签收人名称");
            put("seqNo", "顺序号");

            // UptMainInfoTextChkDoctorDto
            put("edtType", "更新类型【1：只修改当前标本、2：修改所有未审核标本、3：修改指定标本号范围】");
            put("codeRange", "修改标本号范围");
            put("action", "动作【'1':初审、'2':审核人并审核、'3':修改检验人、'4'：只修改审核人不做审核处理】");
            put("acterCode", "操作人编号");
            put("acterNa", "操作人名称");
        }
    };

    private final static Map<String, String> uodateMainInfoMap = new HashMap<String, String>() {
        {
            put("sampleNo", "标本号");
            put("reqNo", "条码号");
            put("reqTime", "申请时间");
            put("sampleType", "样本类型编号");
            put("quantity", "标本量");
            put("feeType", "费别");
            put("reqDept", "申请科室编号");
            put("reqWard", "病区代码");
            put("reqDoctor", "申请医生编号");
            put("reqPurpose", "检验目的，如肝功，肾功，血糖");
            put("testPurpose", "检验目的");
            put("reSampleNo", "复查标本号");
            put("patType", "病人类型");
            put("patNo", "病历号");
            put("patNa", "病人姓名");
            put("sex", "性别1男、2女、3不详");
            put("idType", "证件类型来自字典");
            put("sin", "社会保险号码");
            put("bedNo", "床号");
            put("age", "年龄");
            put("ageUnit", "年龄单位");
            put("secAge", "二级年龄");
            put("secAgeUnit", "二级年龄单位");
            put("telNo", "联系电话");
            put("contacter", "联系人(病人家属)");
            put("phyCycel", "生理周期");
            put("lactation", "哺乳期");
            put("gestation", "妊娠期");
            put("gestationWeek", "孕周数");
            put("gestationTimes", "孕次数");
            put("gestationStage", "孕期");
            put("diagnose", "临床诊断");
            put("description", "备注");
            put("testDoctor", "检验医生编号/上机人");
            put("chkDoctor", "审核医生编号");
            put("chkTime", "审核时间");
            put("isReChk", "是否复核");
            put("firstChkDoctor", "初审医生编号");
            put("firstChkTime", "初审时间");
            put("reChkDoctor", "复核医师编号");
            put("reChkTimt", "复核日期");
            put("isPrint", "是否打印");
            put("printDoctor", "打印人编号");
            put("printTime", "打印时间");
            put("printCount", "打印次数");
            put("isPublish", "是否发布");
            put("samplingDoctor", "采样医生编号");
            put("samplingTime", "采样时间");
            put("samplingSite", "采集部位");
            put("traits", "标本特征");
            put("isLock", "是否锁定");
            put("isCancel", "是否作废");
            put("alarmResult", "报警结果");
            put("positiveFlag", "阳性结果标志");
            put("remake1", "备注1");
            put("remake2", "备注2");
            put("remake3", "备注3");
            put("remake4", "备注4");
            put("executeFlag", "仪器调用接口执行标志");
            put("businessType", "报告单元-业务类型");
            put("unChkDoctor", "授权后消审医生编号");
            put("unChkDoctorNa", "授权后消审医生名称");
            put("seqNo", "顺序号");
            put("signTime", "签收时间");
        }
    };

    private final static Map<String, String> repEtitionMap = new HashMap<String, String>() {{
        put("rptGroup", "报告单元");
        put("maininfoId", "检验主记录id");
        put("repDate", "复查时间");
        put("repDoctor", "复查医生编号");
        put("repDoctorName", "复查医生名称");
    }};

    private final static Map<String, String> rptResultMap = new HashMap<String, String>() {{
        put("sampleda", "检验日期");
        put("rptGroup", "报告单元");
        put("sampleNo", "标本号");
        put("itemDictId", "报告项目ID");
        put("itemNo", "报告项目代号");
        put("itemNa", "报告项目名称");
        put("testResult", "检验结果");
        put("adjustResult", "调整前结果");
        put("od", "OD值");
        put("cutoff", "Cutoff值");
        put("resultFlag", "结果标志");
        put("resultTimeStr", "用于存放结果时间");
        put("ref", "参考范围");
        put("resultDesc", "结果说明");
        put("instrCode", "仪器代号");
        put("instrId", "仪器id");
        put("instrNa", "仪器名称");
        put("isAlarm", "是否危急值");
        put("alarmText", "危急值信息");
        put("rawData", "仪器原始结果 ，不可以修改");
        put("feeCode", "申请项目代号");
        put("feeName", "申请项目名称");
        put("exaMethodId", "检测方法");
        put("displayOrder", "显示顺序");
        put("isNeedToReport", "是否需要报告");
        put("sco", "吸光度与临界值的比值");
        put("ct", "循环数阈值(PCR)");
        put("exaCriticalValueLevelId", "字典报告项目危急值水平字典表主键");
        put("remark1", "备注1");
        put("remark2", "备注2");
        put("remark3", "备注3");
        put("remark4", "备注4");
        put("maininfoId", "检验主记录id");
    }};

    private final static Map<String, String> urlMap = new HashMap<String, String>() {{
        put("/lab/maininfo/updateMaininfo", "1");
        put("/lab/reqMain/insertMaininfoByReqNo", "2");
        put("/lab/maininfo/insertMaininfoByReqNo", "2");
        put("/lab/reqMainBak/insertMaininfoByReqNo", "2");
        put("/lab/maininfo/updateTestChkDoctorAfterAuth", "2");
        put("/lab/maininfo/unChkMainInfo", "2");
        put("/lab/maininfo/unChkBacMainInfo", "2");
        put("/lab/maininfo/updateBacTestChkDoctorAfterAuth", "2");
        put("/lab/maininfoBac/deleteMaininfoBacById", "3");
        put("/lab/maininfo/deleteMaininfoById", "3");
    }};

    ThreadLocal<Long> startTime = new ThreadLocal<>();

    @Pointcut("@annotation(com.ysd.lis.annotation.MainInfoLog)")
    public void operationLog() {
    }

    @Before("operationLog()")
    public void beforeMethod(JoinPoint point) {
        startTime.set(System.currentTimeMillis());
    }

    /**
     * 设置操作异常切入点记录异常日志 扫描所有controller包下操作
     */
    @Pointcut("execution(* com.ysd.lis.controller.lab..*.*(..))")
    public void exceptionLogPointCut() {
    }


    @AfterReturning(value = "operationLog()", returning = "result")
    public void AfterMethod(JoinPoint joinPoint, Object result) {
        saveLog(joinPoint, result);
    }


    private void saveLog(JoinPoint joinPoint, Object result) {
        //result转json对象
        cn.hutool.json.JSONObject resultJson = JSONUtil.parseObj(result);
        BigDecimal bigDecimal = JSONUtil.parseObj(resultJson.get("status")).getBigDecimal("code");
        if (bigDecimal.compareTo(BigDecimal.valueOf(400)) == 0){
            return;
        }


        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        LabMainInfoLog log = new LabMainInfoLog();
        try {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            Map<String, Object> paramsMap = produceParamsMap.apply(joinPoint, signature);

            MainInfoLog annotation = method.getAnnotation(MainInfoLog.class);
            if (null != annotation) {
                log.setModule(annotation.module());
                log.setContent(annotation.content());
                OperationType operationType = annotation.operationType() != null ? annotation.operationType() : OperationType.OTHER;
                log.setOperationType(operationType);
                log.setBusinessName(annotation.businessName());
            }
            Timestamp operate = Timestamp.valueOf(LocalDateTime.now());
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = method.getName();
            methodName = className + "." + methodName + "()";
            log.setMethod(methodName);
            log.setRequestMethod(request.getMethod());
            log.setSampleDate((String) paramsMap.get("sampleda"));
            log.setSampleNumber((String) paramsMap.get("sampleNo"));
            log.setRptGroup((String) paramsMap.get("rptGroup"));
            log.setReqNo((String) paramsMap.get("reqNo"));
            log.setInstrSetup((String) paramsMap.get("instrSetup"));
            log.setMainInfoId((String) (StrUtil.isNotBlank((CharSequence) paramsMap.get("id")) ? paramsMap.get("id") : paramsMap.get("maininfoId")));

            log.setRequestParam(JSON.toJSONString(formatMap(paramsMap, request.getRequestURI())));
            // 插入本次上机记录数据
            log.setMaininfoResult(resultMap(paramsMap, request.getRequestURI(),resultJson));
            // 查看修改的数据
            updateMainInfo(paramsMap, request.getRequestURI(), log);
            log.setResponseParam(JSON.toJSONString(result));
            log.setMachineIp(getIp(request));
            log.setMachineName(getMachineName());
            log.setRequestUrl(request.getRequestURI());
            log.setOperateTime(operate);
            Long takeTime = System.currentTimeMillis() - startTime.get();
            log.setTakeTime(takeTime + "");

            SysUser sysUser = RedisUserManager.getUser();
            if (ToolsUtils.isNotEmpty(sysUser)) {
                log.setUserName(sysUser.getUsername());
                log.setUserId(sysUser.getId());
                log.setOrgId(sysUser.getOrgId());
                SysOrganization sysOrganization = sysOrganizationMapper.selectById(sysUser.getOrgId());
                if (ToolsUtils.isNotEmpty(sysOrganization)) {
                    if (ToolsUtils.isNotEmpty(sysOrganization.getName())) {
                        log.setHospitalName(sysOrganization.getName());
                    }
                    if (ToolsUtils.isNotEmpty(sysOrganization.getCode())) {
                        log.setHospitalCode(sysOrganization.getCode());
                    }
                }
            }

            System.out.println(JSON.toJSONString(log));
            logService.save(log);
        } catch (Exception e) { // 插入数据库
            e.printStackTrace();
            logger.error("mainInfoException", e);
        }
    }


    private Map<String, Object> formatMap(Map<String, Object> paramsMap, String uri) {
        Map<String, Object> reqMap = new HashMap<>();
        switch (uri) {
            case "/lab/maininfo/updateMaininfo":
            case "/lab/maininfo/deleteMaininfoById":
            case "/lab/maininfo/unChkMainInfo":
            case "/lab/maininfo/LabMainInfoPrint":
            case "/lab/reqMain/insertMaininfoByReqNo":
            case "/lab/maininfo/insertMaininfoByReqNo":
            case "/lab/reqMainBak/insertMaininfoByReqNo":
            case "/lab/maininfo/insertMaininfoBySpecimen":
            case "/lab/maininfo/updateTestChkDoctorAfterAuth":
            case "/lab/maininfo/unChkMainInfoMany":
            case "/lab/maininfo/labMainInfoBatchChk":
                for (String key : paramsMap.keySet()) {
                    if (StrUtil.isNotBlank((String) paramsMap.get(key)) && !paramsMap.get(key).equals("null")) {
                        reqMap.put(mainInfoMap.getOrDefault(key, key), (String) paramsMap.get(key));
                    }
                }
                break;
            case "/lab/repetition/addRepetition":
                for (String key : paramsMap.keySet()) {
                    if (StrUtil.isNotBlank((String) paramsMap.get(key)) && !paramsMap.get(key).equals("null")) {
                        reqMap.put(repEtitionMap.getOrDefault(key, key), (String) paramsMap.get(key));
                    }
                }
                break;
            case "/lab/rptResult/insertRptResult":
                for (String key : paramsMap.keySet()) {
                    if (StrUtil.isNotBlank((String) paramsMap.get(key)) && !paramsMap.get(key).equals("null")) {
                        reqMap.put(rptResultMap.getOrDefault(key, key), (String) paramsMap.get(key));
                    }
                }
                break;
            default:
                reqMap.putAll(paramsMap);
                break;
        }
        return reqMap;
    }

    //查询上机数据.类型1根据id,类型2根据联合主键
    private String resultMap(Map<String, Object> paramsMap, String uri,cn.hutool.json.JSONObject resultJson) throws JsonProcessingException {
        String result = "";
        LambdaQueryWrapper<LabMaininfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //循环urlMap的key
        for (String key: urlMap.keySet()) {
            if (uri.contains(key)){
                String s = urlMap.get(key);
                if (ToolsUtils.isNotEmpty(s)) {
                    if (s.equals("1")) {
                        String labMaininfo = (String) paramsMap.get("labMaininfo");
                        String id = JSONObject.parseObject(labMaininfo).getString("id");
                        LabMaininfo maininfo = labMaininfoService.getById(id);
                        if (ToolsUtils.isNotEmpty(maininfo)) {
                            result = JSON.toJSONString(maininfo);
                        }
                    }
                    if (s.equals("2")) {

                        String data = resultJson.get("data").toString();
                        ObjectMapper mapper = new ObjectMapper();
                        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                        LabMaininfoAspect labMaininfoAspect1 = mapper.readValue(data, LabMaininfoAspect.class);

                        result=JSON.toJSONString(labMaininfoAspect1);
                    }
                }
            }
        }


        return result;
    }

    private void updateMainInfo(Map<String, Object> paramsMap, String uri, LabMainInfoLog log) {
        SysUser user = RedisUserManager.getUser();
        String labMaininfo = (String) paramsMap.get("labMaininfo");
        JSONObject jsonObject = new JSONObject();
        if (StringUtils.isBlank(labMaininfo)) {
            jsonObject = new JSONObject(paramsMap);
        } else {
            jsonObject = JSONObject.parseObject(labMaininfo);
        }
        if (StringUtils.isBlank(jsonObject.getString("sampleNo"))||StringUtils.isBlank(jsonObject.getString("rptGroup"))||StringUtils.isBlank(jsonObject.getString("sampleda"))) {
            return;
        }
        List<String> urlList = new ArrayList<>(urlMap.keySet());
        LambdaQueryWrapper<LabMainInfoLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(jsonObject.getString("rptGroup")), LabMainInfoLog::getRptGroup, jsonObject.getString("rptGroup"));
        queryWrapper.eq(StringUtils.isNotBlank(jsonObject.getString("sampleda")), LabMainInfoLog::getSampleDate, jsonObject.getDate("sampleda"));
        queryWrapper.eq(StringUtils.isNotBlank(jsonObject.getString("sampleNo")), LabMainInfoLog::getSampleNumber, jsonObject.getString("sampleNo"));
        queryWrapper.eq(LabMainInfoLog::getDelFlag, 0);
        queryWrapper.in(LabMainInfoLog::getRequestUrl, urlList);
/*
        queryWrapper.and(item -> item.like(LabMainInfoLog::getRequestUrl, "updateMaininfo").or().like(LabMainInfoLog::getRequestUrl, "insertMaininfoByReqNo").or().like(LabMainInfoLog::getRequestUrl, "updateTestChkDoctorAfterAuth"));
*/
        queryWrapper.orderByDesc(LabMainInfoLog::getCreateTime);
        List<LabMainInfoLog> list = logService.list(queryWrapper);
        if (CollectionUtil.isEmpty(list) || StringUtils.isBlank(list.get(0).getMaininfoResult())) {
            if (uri.contains("insertMaininfoByReqNo")) {
                log.setUpdateField("扫码上机");
            }
            return;
        }
        String maininfoResult = list.get(0).getMaininfoResult();
        JSONObject oldObject = JSONObject.parseObject(maininfoResult);
        // 假设 parseObject 包含 LabMaininfo 对象的 JSON 数据
        LabMaininfo oldMaininfo = oldObject.toJavaObject(LabMaininfo.class);
        JSONObject newObject = JSONObject.parseObject(log.getMaininfoResult());
        if (Objects.nonNull(newObject)){
            LabMaininfo newMaininfo = newObject.toJavaObject(LabMaininfo.class);
            switch (uri) {
                case "/lab/maininfo/updateMaininfo":

                    // 比较 LabMaininfo 对象的差异
                    Map<String, Object[]> maininfoDifferences = CompareUtils.compareFields(oldMaininfo, newMaininfo);
                    // 修改值
                    logger.info("LabMaininfo 对象的差异：" + JSON.toJSONString(maininfoDifferences));
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    for (String key : maininfoDifferences.keySet()) {
                        if (Objects.nonNull(maininfoDifferences.get(key))) {
                            String fieldName = uodateMainInfoMap.get(key);
                            if (StrUtil.isNotBlank(fieldName)) {
                                if (Objects.nonNull(maininfoDifferences.get(key)[0])) {
                                    try {
                                        Object oldVa = maininfoDifferences.get(key)[0];
                                        Object newVa = maininfoDifferences.get(key)[1];
                                        if (newVa == null) {
                                            continue;
                                        }
                                        // 去除数字类型
                                        if (!(oldVa instanceof Integer && newVa instanceof Integer)) {
                                            // 解决时间格式问题 毫秒有差异不算修改
                                            String oldFormat = simpleDateFormat.format(oldVa);
                                            String newFormat = simpleDateFormat.format(newVa);
                                            if (oldFormat.equals(newFormat)) {
                                                continue;
                                            }
                                        }

                                    } catch (Exception e) {
                                    }
                                }
                                log.setUpdateField(fieldName);
                                log.setOriginalResult(String.valueOf(maininfoDifferences.get(key)[0]));
                                log.setAmendedResult(String.valueOf(maininfoDifferences.get(key)[1]));
                            }

                        }
                    }
                    break;
                case "/lab/maininfo/updateTestChkDoctorAfterAuth":
                    // 修改检验人
                    if (paramsMap.get("action").equals("3")) {
                        String acterCode = (String) paramsMap.get("acterCode");
                        String testDoctor = uodateMainInfoMap.get("testDoctor");
                        JSONObject updateOldObject = JSONObject.parseObject(maininfoResult);
                        LabMaininfo updateOldMaininfo = updateOldObject.toJavaObject(LabMaininfo.class);
                        log.setUpdateField(testDoctor);
                        log.setOriginalResult(updateOldMaininfo.getTestDoctor());
                        log.setAmendedResult(acterCode);
                    }
                    // 修改审核人
                    if (paramsMap.get("action").equals("4")||paramsMap.get("action").equals("2")) {
                        String acterCode = (String) paramsMap.get("acterCode");
                        String chkDoctor = uodateMainInfoMap.get("chkDoctor");
                        JSONObject updateOldObject = JSONObject.parseObject(maininfoResult);
                        LabMaininfo updateOldMaininfo = updateOldObject.toJavaObject(LabMaininfo.class);
                        if (paramsMap.get("action").equals("2")){
                            log.setUpdateField("审核");
                        }else {
                            log.setUpdateField(chkDoctor);
                        }

                        log.setOriginalResult(updateOldMaininfo.getChkDoctor());
                        log.setAmendedResult(acterCode);

                    }
                    break;
                case "/lab/maininfo/updateBacTestChkDoctorAfterAuth":
                    // 修改检验人
                    if (paramsMap.get("action").equals("3")) {
                        String acterCode = (String) paramsMap.get("acterCode");
                        String testDoctor = uodateMainInfoMap.get("testDoctor");
                        JSONObject updateOldObject = JSONObject.parseObject(maininfoResult);
                        LabMaininfo updateOldMaininfo = updateOldObject.toJavaObject(LabMaininfo.class);
                        log.setUpdateField(testDoctor);
                        log.setOriginalResult(updateOldMaininfo.getTestDoctor());
                        log.setAmendedResult(acterCode);
                    }
                    // 修改审核人
                    if (paramsMap.get("action").equals("4")||paramsMap.get("action").equals("2")) {
                        String acterCode = (String) paramsMap.get("acterCode");
                        String chkDoctor = uodateMainInfoMap.get("chkDoctor");
                        JSONObject updateOldObject = JSONObject.parseObject(maininfoResult);
                        LabMaininfo updateOldMaininfo = updateOldObject.toJavaObject(LabMaininfo.class);
                        if (paramsMap.get("action").equals("2")){
                            log.setUpdateField("审核");
                        }else {
                            log.setUpdateField(chkDoctor);
                        }

                        log.setOriginalResult(updateOldMaininfo.getChkDoctor());
                        log.setAmendedResult(acterCode);

                    }
                    break;
                case "/lab/maininfo/unChkMainInfo":
                    log.setUpdateField("取消审核");
                    log.setOriginalResult(oldMaininfo.getChkDoctor());
                    log.setAmendedResult(newMaininfo.getChkDoctor());
                    break;
                case "/lab/maininfo/unChkBacMainInfo":
                    log.setUpdateField("取消审核");
                    log.setOriginalResult(oldMaininfo.getChkDoctor());
                    log.setAmendedResult(newMaininfo.getChkDoctor());
                    break;
                default:
                    break;
            }
        }
        switch (uri){
            case "/lab/maininfoBac/deleteMaininfoBacById":
                log.setUpdateField("删除上机");
                log.setAmendedResult(user.getRealname());
                break;
            case "/lab/maininfo/deleteMaininfoById":
                log.setUpdateField("删除上机");
                log.setAmendedResult(user.getRealname());
                break;
        }


    }

    private static final BiFunction<JoinPoint, MethodSignature, Map<String, Object>> produceParamsMap = (joinPoint, signature) -> {
        Map<String, Object> paramsMap = new HashMap<>();
        String[] argNames = signature.getParameterNames();
        Object[] argObjects = joinPoint.getArgs();
        List<String> argNameList = Arrays.asList(argNames);
        for (int i = 0; i < argNameList.size(); i++) {
            Class<?> clazz = argObjects[i].getClass();
            Object currentParam = joinPoint.getArgs()[i];
            if (isSimpleType(clazz.getName()) || (argObjects[i] instanceof List)) {
                paramsMap.put(argNameList.get(i), String.valueOf(currentParam));
                continue;
            }
            if (currentParam instanceof ServletRequest) {
                ServletRequest request = (ServletRequest) currentParam;
                Enumeration<String> attr = request.getAttributeNames();
                while (attr.hasMoreElements()) {
                    String attrName = attr.nextElement();
                    String attrValue = "";
                    if (request.getAttribute(attrName) != null) {
                        attrValue = request.getAttribute(attrName).toString();
                    }
                    paramsMap.put(attrName, attrValue);
                }
                continue;
            }
            JSONObject object = (JSONObject) JSONObject.toJSON(currentParam);
            object.keySet().forEach(p -> paramsMap.put(p, String.valueOf(object.get(p))));
        }
        return paramsMap;
    };


    private static boolean isSimpleType(String name) {
        AtomicBoolean result = new AtomicBoolean(false);
        String[] className = {"String", "Integer", "Long", "int", "float", "double", "char"};
        Arrays.asList(className).forEach(n -> {
            if (name.contains(n)) {
                result.set(name.contains(n));
            }
        });
        return result.get();
    }


    private String argsArrayToString(Object[] paramsArray) {
        StringBuilder params = new StringBuilder();
        if (paramsArray != null) {
            for (Object o : paramsArray) {
                if (o != null) {
                    try {
                        Object jsonObj = JSON.toJSON(o);
                        params.append(jsonObj.toString()).append(" ");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return params.toString().trim();
    }


    public static String getIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip.contains(",")) {
            return ip.split(",")[0];
        } else {
            return ip;
        }
    }

    public static String getMachineName() {
        try {
            InetAddress localHost = InetAddress.getLocalHost();
            return localHost.getHostName();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
